package com.yabushan.activiti.service;

import com.alibaba.fastjson.JSON;
import com.yabushan.activiti.domain.*;
import com.yabushan.activiti.util.*;
import com.yabushan.common.core.domain.entity.SysUser;
import com.yabushan.common.utils.DateUtils;
import com.yabushan.common.utils.SecurityUtils;
import com.yabushan.common.utils.StringUtils;
import com.yabushan.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.StartFormData;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.form.*;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ActivitiService {
    @Autowired
    private ProcessDefinitionService processDefinitionService;

    @Autowired
    private ProcessInstanceService processInstanceService;

    @Autowired
    private HistoryQueryService historyQueryService;

    @Autowired
    private FlowUtils flowUtils;
    @Autowired
    private workflowUtilService workflowUtilService;
    @Autowired
    private VacationService vacationService;

    @Autowired
    private FormService formService;

    @Autowired
    private JumpTaskCmdService jumpTaskCmdService;

    @Autowired
    private ISysUserService userService;


    public List<ProcessDefinitionBean> queryDefinition(String definitionKey, String isNew) {
        Boolean isOnlyNew = true;
        if ("false".equals(isNew)) {
            isOnlyNew = false;
        }

        List<ProcessDefinitionBean> definitionBeanList = new ArrayList<ProcessDefinitionBean>();
        ProcessDefinitionBean processDefinitionBean = null;
            List<ProcessDefinition> list = processDefinitionService.queryDefinitionsByDefinitionKey(definitionKey, isOnlyNew);
            // flowEngineService.queryDefinitions();
            if (list != null && list.size() > 0) {
                for (ProcessDefinition processDefinition : list) {
                    processDefinitionBean = new ProcessDefinitionBean();
                    processDefinitionBean.setProcessDefinitionId(processDefinition.getId());
                    processDefinitionBean.setProcessDefinitionKey(processDefinition.getKey());
                    processDefinitionBean.setProcessDefinitionName(processDefinition.getName());
                    processDefinitionBean.setProcessDefinitionResourceBpmn(processDefinition.getResourceName());
                    processDefinitionBean.setProcessDefinitionResourcePng(processDefinition.getDiagramResourceName());
                    processDefinitionBean.setProcessDefinitionVersion(processDefinition.getVersion());
                    processDefinitionBean.setProcessDeploymentId(processDefinition.getDeploymentId());
                    definitionBeanList.add(processDefinitionBean);
                }
            }
        return definitionBeanList;
    }


    public List<StepCodeName> getAllFlowNode(String processDefId) {
        List<StepCodeName> list = workflowUtilService.getJbpmNode(processDefId);
        return list;

    }

    @Transactional(rollbackFor = {Exception.class})
    public String starkFormTask(String processDefinitionKey,String requestUserId,String businessKey, String variables,String isAutoFinishFirstStep){
        if( StringUtils.isNull(variables) || variables.equals("")){
            variables="{}";
        }
        ProcessInstance processInstance = processInstanceService.starkFormTask(processDefinitionKey, requestUserId, businessKey, variables);
        if("1".equals(isAutoFinishFirstStep)){
            List<Task> tasks = processInstanceService.queryMySingleTasks(requestUserId, processInstance.getProcessInstanceId());
            if(tasks.size()!=1){
                String re =  "流程启动成功，无法完成第一步！获取到的流程任务数为："+tasks.size()+">>>"+tasks.toString();
                //log.error(re, new Exception(re));
                return null;
            }else{
                // fininshFormTask(tasks.get(0).getId(),requestUserId,variables);
                Map request = JSON.parseObject(variables);
                request.put("processInstanceId",processInstance.getId());
                processInstanceService.completeFormTask(tasks.get(0).getId(),requestUserId,request,request,request);
                //发送待办
                    //获取流程办理人数据信息
                        //获取下一步办理人








            }
        }
        return processInstance.getId();
    }

    public NextStepAndUser getFirstDealUserByKey(String processKey, String userId, String stepName) {
         return vacationService.getFirstUser(processKey, userId, stepName);

    }

    public List<TaskInfoBean> queryAllTask(String userId) {
        List<Task> list = new ArrayList<Task>();
        List<TaskInfoBean> taskinfo = new ArrayList<TaskInfoBean>();
        // 个人任务
        List<Task> taskList = processInstanceService.queryMySingleTasks(userId);
        if (taskList != null && taskList.size() > 0) {
            list.addAll(taskList);
        }
        // 组任务
        List<Task> groupTaskList = processInstanceService.queryMyGroupTasks(userId);
        if (groupTaskList != null && groupTaskList.size() > 0) {
            list.addAll(groupTaskList);
        }

        for (Task task : list) {
            taskinfo.add(flowUtils.returnTaskInfo(task));
        }
        return taskinfo;

    }


    public TaskInfo getOneTaskInfo(String taskId) {
        TaskInfo taskInfo = new TaskInfo();
        // 获取所有流出线
        List<NextStepAndUser> outLineList = processInstanceService.queryOutComeListByTaskId(taskId);
        // 获取任务
        Task task = processInstanceService.queryTaskInfo(taskId);
        // 根据当前任务获取下一步任务处理人
        List<NextStepAndUser> nextDealUser =null;// vacationService.getNextStepAndUser(task);
        // 获取当前任务处理人
        List<IdentityLink> identityLinks = processInstanceService.getIdentityLinks(taskId);
        StringBuffer buf = new StringBuffer();
        String currentuserId = null;
        if (identityLinks != null && identityLinks.size() != 0) {
            for (IdentityLink identityLink : identityLinks) {
                buf.append(identityLink.getUserId()).append(Constant.SEPARATOR);
            }
        }
        if (buf != null) {
            currentuserId = buf.toString().substring(0, buf.toString().length() - 1);
            taskInfo.setCurrentDealUserId(currentuserId);
        }

        taskInfo.setNextStepAndUser(outLineList);
        taskInfo.setTaskInfoBean(flowUtils.returnTaskInfo(task));
        taskInfo.setAssignee(vacationService.getRequestUserId(taskId));
        return taskInfo;

    }

    public String claimMyTask(String taskId, String dealUser) {

        if (Utils.IsEmpty(taskId) || Utils.IsEmpty(dealUser)) {
            return "参数传入有空值，请检查！";
        }
        // 指派任务
        processInstanceService.claim(taskId, dealUser);
        return null;
    }

    public String trunTask(String taskId, String dealUser) {
        if (Utils.IsEmpty(taskId) || Utils.IsEmpty(dealUser)) {
            return "参数传入有空值，请检查！";
        }
        // 转办任务
        processInstanceService.trunTask(taskId, dealUser);
        return null;
    }
    @Transactional(rollbackFor = {Exception.class})
    public String saveTask(String taskId,String formVariables,String TaskVariables){
        if(formVariables==null){
            formVariables="{}";
        }
        if(TaskVariables==null){
            TaskVariables="{}";
        }
        Map formVariablesMap = JSON.parseObject(formVariables);
        Map TaskVariablesMap = JSON.parseObject(TaskVariables);
        processInstanceService.saveTask(taskId,formVariablesMap,TaskVariablesMap);
        return null;
    }
    @Transactional(rollbackFor = {Exception.class})
    public String fininshFormTask(String taskId,String userId,String formVariables, String TaskVariables,String excutionVariables){


        if(StringUtils.isEmpty(formVariables)||"".equals(formVariables) || formVariables.length()==0 || formVariables==null){
            formVariables="{}";
        }
        if(StringUtils.isEmpty(TaskVariables)||"".equals(TaskVariables) || TaskVariables.length()==0 || TaskVariables==null){
            TaskVariables="{}";
        }
        if(StringUtils.isEmpty(excutionVariables)||"".equals(excutionVariables) || excutionVariables.length()==0 || excutionVariables==null){
            excutionVariables="{}";
        }
        Map formVariablesMap = JSON.parseObject(formVariables);
        Map TaskVariablesMap = JSON.parseObject(TaskVariables);
        Map excutionVariablesMaps = JSON.parseObject(excutionVariables);
        processInstanceService.completeFormTask(taskId,userId,formVariablesMap,TaskVariablesMap,excutionVariablesMaps);

        return null;
    }


    public List<HistoryTaskInfo> getAllFlowStepById(String Id, String flag) {
        List<HistoryTaskInfo> list = new ArrayList<HistoryTaskInfo>();
        List<HistoricProcessInstance> historicProcessInstances = new ArrayList<HistoricProcessInstance>();
        if (Id == null || "".equals(Id)) {
            return null;
        } else {
            if ("1".equals(flag)) {
                // 根据业务主键ID获取历史任务
                // 需要根据业务ID获取所有流程实例
                historicProcessInstances = historyQueryService.getHistoricProcessInstanceByKey(Id, "bid", false, null, null);
                for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
                    list.addAll(vacationService.getAllHistoryStep(historicProcessInstance.getId(), false, null, null));
                }
            } else if ("2".equals(flag)) {
                // 根据流程实例ID获取任务
                list = vacationService.getAllHistoryStep(Id, false, null, null);
            } else {

            }
            StringBuffer userInfo = new StringBuffer();
            if(list.size()!=0){
                for(int i =0;i<list.size();i++){
                     if(StringUtils.isEmpty(list.get(i).getHistoricTaskInstance().getDeleteReason())){
                         //当前任务节点
                         List<IdentityLink> identityLinks = processInstanceService.getIdentityLinks(list.get(i).getHistoricTaskInstance().getId());
                         for(int j =0 ; j<identityLinks.size();j++){
                             String userId = identityLinks.get(j).getUserId();
                             SysUser sysUser = userService.selectUserByUserName(userId);
                             userInfo.append(sysUser.getNickName())
                                     .append("(")
                                     .append(identityLinks.get(j).getUserId())
                                     .append(")").append(",");
                         }
                         String info=userInfo.substring(0,userInfo.length()-1);

                     }else{
                         //已完成任务节点
                         String assignee = list.get(i).getHistoricTaskInstance().getAssignee();
                         //格式化时间
                         String t = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, list.get(i).getHistoricTaskInstance().getEndTime());

                     }
                }
            }

            return list;
        }
    }

    public List<HistoryTaskInfo> getAllHistoryStep(String processInstanceId) {
        List<HistoryTaskInfo> allHistoryStep = vacationService.getAllHistoryStep(processInstanceId, false, null, null);
        return allHistoryStep;
    }


    public List<TaskInfoBean> queryMyTaskByProId(String userId, String processInstanceId) {
        List<TaskInfoBean> taskinfo = new ArrayList<TaskInfoBean>();
        // 个人任务
        List<Task> taskList = processInstanceService.queryMySingleTasks(userId,processInstanceId);
        for (Task task : taskList) {
            taskinfo.add(flowUtils.returnTaskInfo(task));
        }
        return taskinfo;
    }

    public List<FormInfo> getStartFormData(String processDefinitionId){
        StartFormData startFormData= formService.getStartFormData(processDefinitionId);
        List<FormProperty> formProperties = startFormData.getFormProperties();
        List<FormInfo> list=new ArrayList<>();
        FormInfo formInfo=null;
        for(int i=0;i<formProperties.size();i++){
            formInfo=new FormInfo();
            formInfo.setId(formProperties.get(i).getId());
            formInfo.setName(formProperties.get(i).getName());
            formInfo.setReadable(formProperties.get(i).isReadable());
            formInfo.setRequired(formProperties.get(i).isRequired());
            formInfo.setValue(formProperties.get(i).getValue());
            if(formProperties.get(i).getType() instanceof DateFormType){
                formInfo.setType("date");
            }else if(formProperties.get(i).getType() instanceof StringFormType){
                formInfo.setType("string");
            }else if(formProperties.get(i).getType() instanceof LongFormType){
                formInfo.setType("long");
            }else if(formProperties.get(i).getType() instanceof EnumFormType){
                formInfo.setType("enum");
            }else if(formProperties.get(i).getType() instanceof BooleanFormType){
                formInfo.setType("boolean");
            }
            list.add(formInfo);

        }
        return list;
    }

    public TaskFormDataImp getTaskFormData(String taskId) {
        TaskFormData taskFormData = formService.getTaskFormData(taskId);
        TaskFormDataImp taskFormDataImp = new TaskFormDataImp();
        taskFormDataImp.setDeploymentId(taskFormData.getDeploymentId());
        taskFormDataImp.setFormKey(taskFormData.getFormKey());
        taskFormDataImp.setAssignee( taskFormData.getTask().getAssignee());
        taskFormDataImp.setCreateTime(taskFormData.getTask().getCreateTime());//
        taskFormDataImp.setId(taskFormData.getTask().getId());
        taskFormDataImp.setName(taskFormData.getTask().getName());
        taskFormDataImp.setProcessInstanceId(taskFormData.getTask().getProcessInstanceId());
        taskFormDataImp.setProcessDefinitionId(taskFormData.getTask().getProcessDefinitionId());
        taskFormDataImp.setFormPropertyImpl(taskFormData.getFormProperties());
        taskFormDataImp.setExecutionId(taskFormData.getTask().getExecutionId());
        taskFormDataImp.setParentTaskId(taskFormData.getTask().getParentTaskId());
        taskFormDataImp.setTaskDefinitionKey(taskFormData.getTask().getTaskDefinitionKey());
        taskFormDataImp.setVariables(taskFormData.getTask().getProcessVariables());
        return taskFormDataImp;
    }

    public List<HistoryTaskInfo> getMyFinishTask(String userId,Integer firstResult,Integer maxResult) {
        List<HistoricTaskInstance> list = historyQueryService.getMyFinishTask(userId, firstResult, maxResult);
        List<HistoryTaskInfo> historyInfo = vacationService.getHistoryInfo(list);
        return historyInfo;
    }

    public InputStream queryProImg(String businessKey){
        InputStream imageStream=vacationService.queryProImg(businessKey);
        return imageStream;

    }

    public void jumpRunProcessInstanceTask(String dkey,String businessKey,String stepId,String taskUserName){
        jumpTaskCmdService.stopRunProcessInstance(dkey,businessKey,stepId,taskUserName);
    }

}